#include "gy906.h"

#define GY906_PORT	     GPIOB      //PB端口(端口和下面的两个针脚可自定义)

#define GY906_I2C_SCL    PBout(6) //SCL
#define GY906_I2C_SDA    PBout(7) //SDA	 
#define GY906_I2C_READ() PBin(7)

void GY906_SDA_IN(void) 
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
	/*Configure GPIO pin : PA6 */
  GPIO_InitStruct.Pin = SDA_GY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(GY906_PORT, &GPIO_InitStruct);
}

void GY906_SDA_OUT(void) 
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /*Configure GPIO pin : PA6 */
  GPIO_InitStruct.Pin = SDA_GY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  HAL_GPIO_Init(GY906_PORT, &GPIO_InitStruct);
}

/*--------------------------------------------------------------------------------  
//  函数名称：void GY906_I2C_Delay()
//  函数功能：IIC短暂的软件延时
//	说明：对于标准IIC设备，最短延时5.425us，对于最新的IIC设备，或许可以缩短此延时
-----------------------------------------------------------------------------------*/
void GY906_I2C_Delay() 
{
    delay_us(5);
}

//--------------------------------------------------------------------------------------   
//  函数名称：void GY906_I2C_Start() 
//  函数功能：IIC开始信号  
//--------------------------------------------------------------------------------------   
void GY906_I2C_Start(void) 
{
	GY906_SDA_OUT();    		 //SDA线设置为输出
	GY906_I2C_SDA = 1;  	  
	GY906_I2C_SCL = 1; 
	GY906_I2C_Delay();
	
	GY906_I2C_SDA = 0; 		 //产生开始信号
	GY906_I2C_Delay();	
	GY906_I2C_SCL = 0;
  GY906_I2C_Delay();
}

//--------------------------------------------------------------------------------------   
//  函数名称：void GY906_I2C_Stop()
//  函数功能：IIC停止信号  
//--------------------------------------------------------------------------------------   
void GY906_I2C_Stop(void)
{
	GY906_SDA_OUT();		 //sda线输出
	GY906_I2C_SCL = 0;
	GY906_I2C_SDA = 0; 	 //STOP:when CLK is high DATA change form low to high
	GY906_I2C_Delay();
	GY906_I2C_SCL = 1;
	GY906_I2C_SDA = 1;      //发送I2C总线结束信号
	GY906_I2C_Delay();
}

//--------------------------------------------------------------------------------------   
//  函数名称：uint8_t I2C_Get_Ack_From_Slave()
//  函数功能：IIC等待从设备的ACK信号
//	说明：这里使用主从通信协议，CPU是主设备 
//--------------------------------------------------------------------------------------   
uint8_t GY906_I2C_Wait_Ack()
{
	uint8_t ucErrTime = 0;
	
	GY906_SDA_IN();      			// SDA设置为输入  
	GY906_I2C_SDA = 1;
	GY906_I2C_Delay();	   
	GY906_I2C_SCL = 1;
	GY906_I2C_Delay();	 
	while(GY906_I2C_READ())
	{
		ucErrTime++;
		if(ucErrTime > 250)
		{
			GY906_I2C_Stop();
			return 1;
		}
	}
	GY906_I2C_SCL = 0;				//时钟输出0
	return 0;
}

//--------------------------------------------------------------------------------------   
//  函数名称：uint8_t GY906_II2C_Write_Byte(unsigned char Data)
//  函数功能：IIC向从设备写一个字节的数据
//--------------------------------------------------------------------------------------   
void GY906_II2C_Write_Byte(uint8_t txd)
{
	GY906_SDA_OUT(); 	  
	GY906_I2C_SCL = 0;				        //拉低时钟开始数据传输
	for(uint8_t t = 0; t < 8; t++)  //开始准备信号线
	{
		if((txd&0x80) >> 7)
			GY906_I2C_SDA = 1;
		else
			GY906_I2C_SDA = 0;
		txd <<= 1; 	  
		GY906_I2C_Delay();  				//这三个延时都是必须的
		GY906_I2C_SCL = 1;
		GY906_I2C_Delay(); 
		GY906_I2C_SCL = 0;
		GY906_I2C_Delay();
	}
}

//产生ACK应答
void GY906_I2C_Ack(void) 
{
	GY906_I2C_SCL = 0;
	GY906_SDA_OUT();
	GY906_I2C_SDA = 0;
	GY906_I2C_Delay();
	GY906_I2C_SCL = 1;
	GY906_I2C_Delay();
	GY906_I2C_SCL = 0;
}

// 不产生ACK应答		    
static void GY906_I2C_NAck(void)
{
	GY906_I2C_SCL = 0;
	GY906_SDA_OUT();
	GY906_I2C_SDA = 1;
	GY906_I2C_Delay();
	GY906_I2C_SCL = 1;
	GY906_I2C_Delay();
	GY906_I2C_SCL = 0;
}

//--------------------------------------------------------------------------------------   
//  函数名称：uint8_t GY906_I2C_READ_Byte(unsigned char* recv)
//  函数功能：IIC从从设备读一个字节的数据
//--------------------------------------------------------------------------------------   
static uint8_t GY906_I2C_READ_Byte(void) 
{
	uint8_t i = 0,receive = 0;
	
	GY906_SDA_IN();					 // SDA设置为输入
	for(i = 0;i < 8;i++ )
	{
		GY906_I2C_SCL = 0; 
		GY906_I2C_Delay();
		GY906_I2C_SCL = 1;
		receive <<= 1;
		if(GY906_I2C_READ())
			receive++;   
		GY906_I2C_Delay(); 
	}					 
//	if (!ack)
//		I2C_NAck();				 // 发送nACK
//	else
//		I2C_Ack(); 				 // 发送ACK   
	return receive;
}
/*-------------------------------------结束------------------------------------------*/   

#define GY906_Slave_WR               0
#define GY906_Slave_RD               1

uint8_t GY906_BAA_Init(void) 
{
	// SCL / SDA	
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	
	__HAL_RCC_GPIOB_CLK_ENABLE();
	
  /*Configure GPIO pin : PB6 PB7*/
  GPIO_InitStruct.Pin = SCL_GY_Pin|SDA_GY_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GY906_PORT, &GPIO_InitStruct);
		
	GY906_I2C_SCL = 1; 
	GY906_I2C_SDA = 1;
//	GY906_I2C_Delay();
//	GY906_I2C_Delay(); 

	// 判断设备存在
//	GY906_I2C_Start();
//  GY906_II2C_Write_Byte(GY906_SlaveAddress);
//	if(GY906_I2C_Wait_Ack())
//	{
//		printf("I2C NO Ack\r\n");
//		GY906_I2C_Stop();
//		GY906_I2C_Delay(); 
//		GY906_I2C_Delay();
//		return 1;
//	}
//	GY906_I2C_Stop();
//	GY906_I2C_Delay(); 
//	GY906_I2C_Delay()

	return 0;
}

/*******************************************************************************
* Function Name  : PEC_calculation
* Description    : Calculates the PEC of received bytes
* Input          : pec[]
* Output         : None
* Return         : pec[0]-this byte contains calculated crc value
*******************************************************************************/
uint8_t PEC_Calculation(uint8_t pec[]) 
{
	uint8_t        crc[6];
	uint8_t        BitPosition=47;
	uint8_t        shift;
	uint8_t        i;
	uint8_t        j;
	uint8_t        temp;	
	do
	{
		/*Load pattern value 0x000000000107*/
		crc[5]=0;
		crc[4]=0;
		crc[3]=0;
		crc[2]=0;
		crc[1]=0x01;
		crc[0]=0x07;
		/*Set maximum bit position at 47 ( six bytes byte5...byte0,MSbit=47)*/
		BitPosition=47;
		/*Set shift position at 0*/
		shift=0;
		/*Find first "1" in the transmited message beginning from the MSByte byte5*/
		i=5;
		j=0;
		while((pec[i]&(0x80>>j))==0 && i>0)
		{
			BitPosition--;
			if(j<7)
			{
					j++;
			}
			else
			{
					j=0x00;
					i--;
			}
		}/*End of while */

		/*Get shift value for pattern value*/
		shift=BitPosition-8;
		/*Shift pattern value */
		while(shift)
		{
			for(i=5; i<0xFF; i--)
			{
					if((crc[i-1]&0x80) && (i>0))
					{
							temp=1;
					}
					else
					{
							temp=0;
					}
					crc[i]<<=1;
					crc[i]+=temp;
			}/*End of for*/
			shift--;
		}/*End of while*/
		/*Exclusive OR between pec and crc*/
		for(i=0; i<=5; i++)
		{
			pec[i] ^=crc[i];
		}/*End of for*/
	}
	while(BitPosition>8); /*End of do-while*/
	return pec[0];
}

/***************************************
    向I2C设备写入一个字节数据
****************************************/
uint8_t GY906_BAA_Single_Write(uint8_t cmd,uint16_t data,uint8_t pec) 
{
	// 起始信号
	GY906_I2C_Start();   

	// 从机地址
	GY906_II2C_Write_Byte((GY906_SlaveAddress | GY906_Slave_WR));
	if(GY906_I2C_Wait_Ack())
	{
			GY906_I2C_Stop();
			return 1;
	}
    
    // 寄存器地址
    GY906_II2C_Write_Byte(cmd);
	if(GY906_I2C_Wait_Ack())
	{
			GY906_I2C_Stop();
			return 1;
	}
    
	// 设备数据
	GY906_II2C_Write_Byte((uint8_t)(data>>8));
	if(GY906_I2C_Wait_Ack())
	{
			GY906_I2C_Stop();
			return 1;
	}
	GY906_II2C_Write_Byte((uint8_t)(data>>0));
	if(GY906_I2C_Wait_Ack())
	{
			GY906_I2C_Stop();
			return 1;
	} 
	GY906_II2C_Write_Byte(pec);
	if(GY906_I2C_Wait_Ack())
    {
        GY906_I2C_Stop();
        return 1;
    }  	
    // 结束信号
    GY906_I2C_Stop();
    return 0;
}

//***************************************
//    从I2C设备读取一个字节数据
//***************************************
uint16_t GY906_BAA_Single_Read(uint8_t cmd) 
{
  uint16_t data = 0;
	uint8_t  pec = 0;
	
	uint8_t DataL=0;             // Low data byte storage
  uint8_t DataH=0;             // High data byte storage    
	uint8_t arr[6] = {0};
	uint8_t PecReg;
	
	do{
		// 起始信号
		GY906_I2C_Start();			
		// 从机地址
		GY906_II2C_Write_Byte((GY906_SlaveAddress | GY906_Slave_WR));
		if(GY906_I2C_Wait_Ack())
		{
			GY906_I2C_Stop();
			return 1;
		}

		// 寄存器地址
		GY906_II2C_Write_Byte(cmd);
		if(GY906_I2C_Wait_Ack())
		{
			GY906_I2C_Stop();
			return 1;
		}
		
		// 起始信号
		GY906_I2C_Start();
		
		// 从机地址
		GY906_II2C_Write_Byte((GY906_SlaveAddress | GY906_Slave_RD));
		if(GY906_I2C_Wait_Ack())
		{
			GY906_I2C_Stop();
			return 1;
		}
		
		// 读出数据
		DataL = GY906_I2C_READ_Byte(); // 应答
		GY906_I2C_Ack();
		DataH = GY906_I2C_READ_Byte(); // 应答
		GY906_I2C_Ack();
		
		// PEC
		pec   = GY906_I2C_READ_Byte(); // 应答
		GY906_I2C_NAck();
		
		arr[5] = GY906_SlaveAddress;        
		arr[4] = cmd;
		arr[3] = GY906_SlaveAddress + 1;         //Load array arr
		arr[2] = DataL;                 
		arr[1] = DataH;                
		arr[0] = 0;                   
		PecReg = PEC_Calculation(arr);     //Calculate CRC
		
		// 结束信号   
		GY906_I2C_Stop();
	}while(PecReg != pec);
	
    data = (uint16_t)(DataH<<8) + (uint16_t)(DataL<<0);
	return data;
}

float GY906_BAA_Temp_Read(void)
{
	float temp;
	
	temp = GY906_BAA_Single_Read(0x07)*0.02 - 273.15;
	return temp;
}

